Skip to content

Fix worktree removal timing out on large install trees#3902

Open
jakeleventhal wants to merge 5 commits into
pingdotgg:mainfrom
jakeleventhal:t3code/fix-worktree-remove-timeout
Open

Fix worktree removal timing out on large install trees#3902
jakeleventhal wants to merge 5 commits into
pingdotgg:mainfrom
jakeleventhal:t3code/fix-worktree-remove-timeout

Conversation

@jakeleventhal

@jakeleventhal jakeleventhal commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

Summary

Solves #3593

  • Forced worktree removal was hitting a 15s git worktree remove timeout on multi-GB trees with setup artifacts like node_modules.
  • Delete the working tree via the filesystem first (5m budget), then let git clean up registration metadata with a longer timeout.
  • Update the worktree remove integration test to exercise the force path used by thread deletion.

Test plan

  • Delete a thread that owns a worktree with installed deps and choose “Delete the worktree too”
  • Confirm the toast no longer reports Git command timed out / worktree removal failure
  • Confirm the worktree directory is gone under ~/.t3/worktrees/... and git worktree list no longer lists it
  • vp test in apps/server for src/vcs/GitVcsDriverCore.test.ts

Made with Cursor

Note

Fix worktree removal timing out on large install trees by pre-deleting directories

  • removeWorktree(force) in GitVcsDriverCore.ts now pre-deletes the worktree directory via fileSystem.remove before calling git worktree remove, avoiding git's own slow filesystem traversal on large trees.
  • Pre-deletion only runs when the target path is a registered linked worktree (verified via git worktree list --porcelain), preventing accidental deletion of unregistered directories.
  • Transient failures (Busy, WouldBlock, Unknown) are retried up to 50 times with 100ms spacing; the overall pre-delete step times out after 5 minutes, and the final git step uses a 60s timeout.
  • Adds parsePorcelainWorktreePaths to extract worktree paths from porcelain output, and new tests covering retry behavior, safety checks on non-registered paths, and filesystem cleanup.

Macroscope summarized 2c45b97.

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@coderabbitai

coderabbitai Bot commented Jul 11, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: c81a882e-b9f9-4e64-9fb8-192b1e7c96fc

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions github-actions Bot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:M 30-99 changed lines (additions + deletions). labels Jul 11, 2026
Comment thread apps/server/src/vcs/GitVcsDriverCore.ts
@macroscopeapp

macroscopeapp Bot commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Needs human review

1 blocking correctness issue found. This PR introduces new filesystem deletion and retry logic for worktree removal. Two unresolved review comments identify potential bugs: incorrect parsing of paths with special characters, and bypassing worktree locks which could cause data loss. These substantive issues warrant human review.

You can customize Macroscope's approvability policy. Learn more.

Comment thread apps/server/src/vcs/GitVcsDriverCore.ts
@github-actions github-actions Bot added size:L 100-499 changed lines (additions + deletions). and removed size:M 30-99 changed lines (additions + deletions). labels Jul 12, 2026
Comment thread apps/server/src/vcs/GitVcsDriverCore.ts
jakeleventhal and others added 4 commits July 18, 2026 10:03
Force-remove deletes the working tree via the filesystem first so git only cleans registration metadata, instead of timing out while walking multi-GB node_modules.

Co-authored-by: Cursor <cursoragent@cursor.com>
Only wipe the directory after confirming the path is a linked entry from `git worktree list`, so mistyped or non-worktree paths are left intact.

Co-authored-by: Cursor <cursoragent@cursor.com>
If listing times out or fails, skip the filesystem pre-delete and still run git worktree remove instead of aborting the whole operation.

Co-authored-by: Cursor <cursoragent@cursor.com>
@jakeleventhal
jakeleventhal force-pushed the t3code/fix-worktree-remove-timeout branch from 35a62d9 to 4ce5dfa Compare July 18, 2026 14:06
return splitNullSeparatedPaths(result.stdout, result.stdoutTruncated);
}

export function parsePorcelainWorktreePaths(stdout: string): string[] {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Medium vcs/GitVcsDriverCore.ts:239

parsePorcelainWorktreePaths splits the porcelain output on \n and trims each path, so worktree paths containing a newline or trailing whitespace are parsed incorrectly. For such a worktree, the registration check fails and the filesystem pre-delete is skipped, causing removal to fall back to the slow git worktree remove path this PR is meant to avoid. Git documents that worktree list --porcelain -z must be used to correctly parse paths containing newlines. Consider switching to the -z (NUL-delimited) format and splitting on \0 instead.

🤖 Copy this AI Prompt to have your agent fix this:
In file @apps/server/src/vcs/GitVcsDriverCore.ts around line 239:

`parsePorcelainWorktreePaths` splits the porcelain output on `\n` and trims each path, so worktree paths containing a newline or trailing whitespace are parsed incorrectly. For such a worktree, the registration check fails and the filesystem pre-delete is skipped, causing removal to fall back to the slow `git worktree remove` path this PR is meant to avoid. Git documents that `worktree list --porcelain -z` must be used to correctly parse paths containing newlines. Consider switching to the `-z` (NUL-delimited) format and splitting on `\0` instead.

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 4ce5dfa. Configure here.

onSome: () => Effect.void,
}),
),
);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Force delete bypasses worktree locks

Medium Severity

The force path recursively deletes a linked worktree via the filesystem after only checking porcelain path membership. It never inspects a porcelain locked record, and the later git worktree remove still passes only a single --force. Git refuses locked worktrees unless forced twice, so a locked tree can be wiped on disk before git rejects the removal, leaving data gone and cleanup failing.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 4ce5dfa. Configure here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L 100-499 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant